import 'dart:ui' as ui;
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:amap_flutter_map/amap_flutter_map.dart';
import 'package:amap_flutter_base/amap_flutter_base.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:dio/dio.dart';

/// 故事封面管理器
/// 用于创建带封面图的自定义 Marker
class StoryCoverMarkerHelper {
  // 图标缓存 - 避免重复下载和创建
  static final Map<String, BitmapDescriptor> _iconCache = {};
  
  // 原始图片数据缓存 - 避免重复下载，支持快速重绘不同尺寸
  static final Map<String, Uint8List> _imageDataCache = {};
  
  // 占位符图标缓存 - 按尺寸缓存
  static final Map<double, BitmapDescriptor> _placeholderCache = {};
  
  /// 创建占位符图标
  /// 用于在真实图片下载期间显示
  static Future<BitmapDescriptor> createPlaceholderIcon({
    double size = 80.0,
  }) async {
    // 检查缓存
    if (_placeholderCache.containsKey(size)) {
      print('✅ 使用缓存的占位符图标: ${size.toInt()}px');
      return _placeholderCache[size]!;
    }
    
    try {
      print('🎨 创建占位符图标: ${size.toInt()}px');
      
      // 创建画布
      final recorder = ui.PictureRecorder();
      final canvas = Canvas(
        recorder,
        Rect.fromLTWH(0, 0, size, size),
      );

      // 1. 绘制白色背景
      final bgPaint = Paint()..color = Colors.white;
      canvas.drawRRect(
        RRect.fromRectAndRadius(
          Rect.fromLTWH(0, 0, size, size),
          const Radius.circular(8),
        ),
        bgPaint,
      );

      // 2. 绘制浅灰色内容区域
      final contentPaint = Paint()..color = const Color(0xFFF5F5F5);
      canvas.drawRRect(
        RRect.fromRectAndRadius(
          Rect.fromLTWH(4, 4, size - 8, size - 8),
          const Radius.circular(6),
        ),
        contentPaint,
      );

      // 3. 绘制 loading 圆圈
      final circleCenter = Offset(size / 2, size / 2);
      final circleRadius = size / 5;
      
      // 外圈 - 淡灰色
      final outerCirclePaint = Paint()
        ..color = const Color(0xFFE0E0E0)
        ..style = PaintingStyle.stroke
        ..strokeWidth = 2.5;
      canvas.drawCircle(circleCenter, circleRadius, outerCirclePaint);
      
      // 内部弧线 - 深灰色（表示 loading）
      final arcPaint = Paint()
        ..color = const Color(0xFF9E9E9E)
        ..style = PaintingStyle.stroke
        ..strokeWidth = 2.5
        ..strokeCap = StrokeCap.round;
      canvas.drawArc(
        Rect.fromCircle(center: circleCenter, radius: circleRadius),
        -1.57, // 起始角度（-90度，从顶部开始）
        3.14,  // 扫过角度（180度）
        false,
        arcPaint,
      );

      // 4. 绘制边框
      final borderPaint = Paint()
        ..color = const Color(0xFFE0E0E0)
        ..style = PaintingStyle.stroke
        ..strokeWidth = 2;
      canvas.drawRRect(
        RRect.fromRectAndRadius(
          Rect.fromLTWH(4, 4, size - 8, size - 8),
          const Radius.circular(4),
        ),
        borderPaint,
      );

      // 5. 转换为图片
      final picture = recorder.endRecording();
      final image = await picture.toImage(size.toInt(), size.toInt());
      final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
      final bytes = byteData!.buffer.asUint8List();

      // 6. 创建 BitmapDescriptor
      final icon = BitmapDescriptor.fromBytes(bytes);
      
      // 7. 存入缓存
      _placeholderCache[size] = icon;
      print('✅ 占位符图标创建并缓存: ${size.toInt()}px');
      
      return icon;
    } catch (e) {
      print('❌ 创建占位符图标失败: $e');
      // 降级：返回默认 marker
      return BitmapDescriptor.defaultMarker;
    }
  }
  
  /// 从网络图片创建自定义 Marker 图标
  /// 使用双层缓存机制：图片数据缓存 + 图标缓存
  static Future<BitmapDescriptor?> createCoverMarkerIcon(
    String imageUrl, {
    double size = 80.0,
  }) async {
    // 生成缓存key
    final cacheKey = '$imageUrl-$size';
    
    // 1. 先检查图标缓存（最快）
    if (_iconCache.containsKey(cacheKey)) {
      print('✅ 使用缓存的封面图标: $imageUrl (${size.toInt()}px)');
      return _iconCache[cacheKey];
    }
    
    Uint8List? imageData;
    
    // 2. 检查图片数据缓存
    if (_imageDataCache.containsKey(imageUrl)) {
      print('✅ 使用缓存的图片数据: $imageUrl');
      imageData = _imageDataCache[imageUrl];
    } else {
      // 3. 需要下载图片
      try {
        print('📥 下载封面图片: $imageUrl');
        
        final dio = Dio();
        final response = await dio.get<List<int>>(
          imageUrl,
          options: Options(responseType: ResponseType.bytes),
        );
        
        if (response.statusCode != 200 || response.data == null) {
          print('❌ 下载失败: HTTP ${response.statusCode}');
          return null;
        }
        
        imageData = Uint8List.fromList(response.data!);
        
        // 缓存原始图片数据
        _imageDataCache[imageUrl] = imageData;
        print('✅ 下载并缓存: ${imageData.length} bytes');
      } catch (e) {
        print('❌ 下载异常: $e');
        return null;
      }
    }
    
    try {
      // 4. 解码图片为指定大小
      final codec = await ui.instantiateImageCodec(
        imageData!,
        targetWidth: size.toInt(),
        targetHeight: size.toInt(),
      );
      final frame = await codec.getNextFrame();
      final image = frame.image;

      // 5. 创建画布并绘制
      final recorder = ui.PictureRecorder();
      final canvas = Canvas(
        recorder,
        Rect.fromLTWH(0, 0, size, size),
      );

      // 绘制白色背景
      final bgPaint = Paint()..color = Colors.white;
      canvas.drawRRect(
        RRect.fromRectAndRadius(
          Rect.fromLTWH(0, 0, size, size),
          const Radius.circular(8),
        ),
        bgPaint,
      );

      // 绘制阴影
      final shadowPaint = Paint()
        ..color = Colors.black.withOpacity(0.2)
        ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 3);
      canvas.drawRRect(
        RRect.fromRectAndRadius(
          Rect.fromLTWH(2, 2, size - 4, size - 4),
          const Radius.circular(6),
        ),
        shadowPaint,
      );

      // 绘制图片
      canvas.drawImageRect(
        image,
        Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble()),
        Rect.fromLTWH(4, 4, size - 8, size - 8),
        Paint(),
      );

      // 绘制边框
      final borderPaint = Paint()
        ..color = Colors.white
        ..style = PaintingStyle.stroke
        ..strokeWidth = 2;
      canvas.drawRRect(
        RRect.fromRectAndRadius(
          Rect.fromLTWH(4, 4, size - 8, size - 8),
          const Radius.circular(4),
        ),
        borderPaint,
      );

      // 6. 转换为图片
      final picture = recorder.endRecording();
      final finalImage = await picture.toImage(size.toInt(), size.toInt());
      final byteData = await finalImage.toByteData(format: ui.ImageByteFormat.png);
      final bytes = byteData!.buffer.asUint8List();

      // 7. 创建 BitmapDescriptor
      final icon = BitmapDescriptor.fromBytes(bytes);
      
      // 8. 存入图标缓存
      _iconCache[cacheKey] = icon;
      print('✅ 创建并缓存封面图标: $imageUrl (${size.toInt()}px)');
      
      return icon;
    } catch (e) {
      print('❌ 创建封面图标失败: $e');
      return null;
    }
  }
  
  /// 清理所有缓存
  /// 可在内存紧张时调用
  static void clearAllCache() {
    _iconCache.clear();
    _imageDataCache.clear();
    _placeholderCache.clear();
    print('封面缓存已清理（图标 + 图片数据 + 占位符）');
  }
  
  /// 只清理图标缓存，保留图片数据
  /// 用于需要重新生成不同尺寸的图标时
  static void clearIconCache() {
    _iconCache.clear();
    print('封面图标缓存已清理（保留图片数据缓存）');
  }
  
  /// 获取缓存大小
  static Map<String, int> getCacheSize() {
    return {
      'icons': _iconCache.length,
      'images': _imageDataCache.length,
      'placeholders': _placeholderCache.length,
    };
  }

  /// 根据缩放级别获取合适的图标大小（单位：像素）
  /// 
  /// 核心思路：封面表示地图上的一个固定物理区域（比如50米×50米）
  /// 当地图缩放时，这个区域在屏幕上占用的像素数会变化
  /// 
  /// 公式：屏幕像素 = 物理距离(米) / 每像素对应的米数
  /// 
  /// 高德地图每像素对应的米数计算：
  /// metersPerPixel = 156543.03392 * cos(latitude) / (2^zoom)
  /// 简化版（假设纬度39°，cos(39°)≈0.777）：
  /// metersPerPixel ≈ 121600 / (2^zoom)
  static double getSizeForZoom(double zoom) {
    // 核心思路：
    // 1. 封面代表地图上的一个固定物理区域
    // 2. 物理尺寸根据缩放级别适当调整（远景大一些，近景小一些）
    // 3. 转换为屏幕像素时考虑地图比例尺
    // 4. 最终限制在合理的屏幕范围内
    
    // 1. 根据缩放级别确定物理尺寸（米）
    double physicalSizeInMeters;
    
    if (zoom < 12) {
      // 远景 (zoom 3-11)：100-200米，像一个小区域的标识
      physicalSizeInMeters = 100.0 + (zoom - 3) * 11.0;
      physicalSizeInMeters = physicalSizeInMeters.clamp(100.0, 200.0);
    } else if (zoom < 16) {
      // 中景 (zoom 12-15)：50-100米，像一条街道的宽度
      physicalSizeInMeters = 100.0 - (zoom - 12) * 12.5;
      physicalSizeInMeters = physicalSizeInMeters.clamp(50.0, 100.0);
    } else {
      // 近景 (zoom 16+)：20-50米，像一个建筑的大小
      physicalSizeInMeters = 50.0 - (zoom - 16) * 7.5;
      physicalSizeInMeters = physicalSizeInMeters.clamp(20.0, 50.0);
    }
    
    // 2. 计算该缩放级别下每像素对应的米数
    // 高德地图公式：metersPerPixel = 156543.03392 * cos(lat) / (2^zoom)
    // 简化版（假设中纬度地区）：metersPerPixel ≈ 121600 / (2^zoom)
    final metersPerPixel = 121600.0 / (1 << zoom.toInt());
    
    // 3. 计算物理尺寸对应的屏幕像素
    double sizeInPixels = physicalSizeInMeters / metersPerPixel;
    
    // 4. 限制在合理的屏幕像素范围内
    //    最小60px（保证封面清晰可见）
    //    最大250px（避免占据整个屏幕）
    sizeInPixels = sizeInPixels.clamp(60.0, 250.0);
    
    return sizeInPixels;
  }
}

/// 故事封面管理器 Widget
/// 使用自定义 Marker 的方式显示故事封面
class StoryCoverManager extends StatefulWidget {
  final List<StoryCoverData> storyCovers;
  final AMapController mapController;
  final double currentZoom;
  final Function(String storyId)? onStoryCoverTap;

  const StoryCoverManager({
    super.key,
    required this.storyCovers,
    required this.mapController,
    required this.currentZoom,
    this.onStoryCoverTap,
  });

  @override
  State<StoryCoverManager> createState() => _StoryCoverManagerState();
}

class _StoryCoverManagerState extends State<StoryCoverManager> {
  @override
  Widget build(BuildContext context) {
    // 不需要在 UI 中显示任何内容
    // 封面通过 Marker 的方式添加到地图上
    return const SizedBox.shrink();
  }
}

/// 故事封面数据
class StoryCoverData {
  final String storyId;
  final String coverImageUrl;
  final double latitude;
  final double longitude;
  final double size; // 覆盖层大小（米）

  StoryCoverData({
    required this.storyId,
    required this.coverImageUrl,
    required this.latitude,
    required this.longitude,
    this.size = 50.0, // 默认50米
  });
}

